library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity pseudoTop is
	generic(W:integer:=37;
		  ABUS:integer:=18;  --BUS DE DIRECCION DE LA RAM
		  DBUS: integer:=16; --BUS DE DATOS DE LA RAM
                -- Default settings:
                -- 19200 baud, 8 data bits, 1 stop bit
              DBIT: integer:=8;               -- # data bits
              SB_TICK: integer:=16;   -- # ticks for stop bits. 16/24/32 
              DVSR: integer:= 16;    -- baud rate divisor
              DVSR_BIT: integer:=8   -- # bits of DVSR
		  );
	port(
            outX,outY,outZ:            out std_logic_vector(3*DBUS-1 downto 0);
            mem_read_busy_out:         out std_logic;
		read_enable: in std_logic:='1'; 
            mode_out: out std_logic
	    );
end entity;

architecture arch of pseudoTop is
signal clk, reset: std_logic:='0';

signal tick, rx, rx_done_tick: std_logic;
signal rx_dout,tx_din: std_logic_vector(7 downto 0);
signal tx,tx_start, tx_done_tick, tx_start_bis: std_logic;

signal ad: std_logic_vector(ABUS-1 downto 0); 
signal we_n, oe_n: std_logic;
signal dio_a: std_logic_vector(DBUS-1 downto 0);
signal ce_a_n, ub_a_n, lb_a_n: std_logic;

---------------------SIMULADOR???
signal done_delayed: std_logic;
signal download:boolean:=FALSE;
signal dump:boolean:=FALSE;
type data_file_t is file of character;
file datos: data_file_t open read_mode IS "./datos.txt";

-------------------------------------------
--PARSER OUTPUT
signal is_digit, is_blank, is_esc,is_minus: std_logic;
--BCD2BIN OUTPUT
signal magnitude_bin:std_logic_vector(W-1 downto 0);
signal sign_bin: std_logic;
signal new_coord_flag: std_logic;
--COMPLEMENTO A DOS OUTPUT
signal unsigned_bin: std_logic_vector(W-1 downto 0);



--LOGICA EN EL ADDRESS COUNTER
signal reset_address: std_logic;
signal enable_address_counter: std_logic;

--ADDRESS COUNTER
signal sram_address: std_logic_vector(ABUS-1 downto 0);

--MEMORY LOADER
signal mem_load_crash: std_logic; --HACEMO' ALGO CON ESTO????
signal mem_load, sram_ready: std_logic;
signal sram_write_data_bus: std_logic_vector(DBUS-1 downto 0);

--LOGICA EN EL CONTROLADOR DE MEMORIA
signal mem,mem_delayed: std_logic;

--CONTROLADOR DE MEMORIA
signal sram_read_data_bus: std_logic_vector(DBUS-1 downto 0);

--MEMORY READER
signal new_vector_tick: std_logic;

--MODO
signal mode, notmode, esc_flag, is_esc_aux,change_enable: std_logic; -- '0'=UART / '1'=VGA

--CONTROL ADDRESS
signal max_address: std_logic_vector(ABUS-1 downto 0);
signal address_overflow: std_logic;

signal mem_read_add_trig,read_enable_aux: std_logic;
signal mem_read: std_logic; --MEM_READ
signal mem_read_busy: std_logic;


-------------------------------------------

begin

baud_gen_unit: entity work.mod_m_counter(arch)
	generic map(M=>DVSR, N=>DVSR_BIT)
	port map(clk => clk, reset => reset,
			q=> open, max_tick=> tick);

UART0_RX:entity work.uart_rx(arch)
	generic map(DBIT=>DBIT, SB_TICK=>SB_TICK)
	port map(clk=>clk, reset=>reset, s_tick => tick,
		rx=> rx, rx_done_tick => rx_done_tick,
		dout=> rx_dout);

UART0_TX:entity work.uart_tx(arch)
		generic map(DBIT=>DBIT, SB_TICK=>SB_TICK)
		port map(clk=>clk, reset=>reset,
			tx_start=>tx_start,
			s_tick=>tick, din=>tx_din,
			tx_done_tick=>tx_done_tick, tx=>tx);

PARSER0:entity work.ascii_parser(arch)
	port map (clk=>clk, reset=>reset,ascii => rx_dout, rx_done_tick=>rx_done_tick,
			is_digit=>is_digit, is_blank=> is_blank, is_esc => is_esc, is_minus => is_minus);

BCD2BIN0:entity work.bcd2binV2(arch)
        	generic map(W=>W)
		port map (clk=>clk, reset=>reset, bcd_in=>rx_dout(3 downto 0),
			  dout=>magnitude_bin, new_output_flag => new_coord_flag,
			  sign => sign_bin, is_digit => is_digit, is_blank =>is_blank,
			  is_minus => is_minus, enable=>rx_done_tick);

TWOS0:entity work.twosComplement(arch)
	generic map(W=>W)
	port map(din=>magnitude_bin,dout=>unsigned_bin,sign=>sign_bin);

ADDCOUNT0:entity work.addressCounter(arch)
	generic map (ABUS=>ABUS)
	port map(clk=>clk, reset=>reset_address, enable=>enable_address_counter, -- El enable se dispara con mem.
		address_out=>sram_address);

MEMLOAD0:entity work.memoryLoader(arch)
	generic map (W=>W, DBUS=>DBUS)
	port map(clk=>clk, reset=>reset, crash_flag=>mem_load_crash,
			enable=>new_coord_flag, din=>unsigned_bin, sign_in=>sign_bin,
			mem_out=>mem_load, ready=>sram_ready,
			dout=>sram_write_data_bus);

MEMCTRL0: entity work.sram_ctrl(arch)
	port map(clk=>clk, reset=>reset, mem=>mem,rw=>mode, addr=>sram_address,
			data_f2s=>sram_write_data_bus, ready=>sram_ready,
			data_s2f_r=>sram_read_data_bus, data_s2f_ur=>open, --cambiar 
			ad=>ad, we_n=>we_n, oe_n=>oe_n, dio_a=>dio_a,
			ce_a_n=>ce_a_n, ub_a_n=>ub_a_n, lb_a_n=>lb_a_n);


RAM: entity work.sram(behavior)
	generic map( size => 100 , adr_width => 18, width => 16)
	port map(
        nOE => oe_n,
        nWE => we_n,      
        nCE => ce_a_n,
	A => ad,
	D => dio_a,
	dump => dump
	  );

MEM_READ0:entity work.memoryReader(arch)
	generic map ( DBUS=>DBUS, WORDS=>3)
	port map (clk => clk, reset => reset, addTrig => mem_read_add_trig,
			read=>read_enable_aux, outX => outX, outY=> outY, 
			outZ=>outZ, busy_out=>mem_read_busy, 
			new_vector_tick=>new_vector_tick, mem_out => mem_read,
			ready=>sram_ready,din=>sram_read_data_bus);	


--Modo "free running"
read_enable_aux <= NOT mem_read_busy  AND read_enable AND mode;

--Control de cambio de modo
--El latch espera que se desocupe la ram para cambiar de modo.
is_esc_aux<=is_esc AND rx_done_tick;
ESC_FFD0:entity work.FFD(arch)
		generic map(W => 1)
		port map(clk=>clk,reset=>reset, set=>is_esc_aux, prevQ(0)=>'1', Q(0)=>esc_flag);

--TODO:Explota en ficheros mal terminados (Que no terminan en \n<EOF>)
ESC_LATCH0:entity work.LATCH(arch)
		generic map(W => 1)
		port map(reset=>reset, set=>sram_ready, prevQ(0)=>esc_flag, Q(0)=>mode);

--Cableado

--Este latch guarda la maxima dirección
notmode <= not mode;
	
ADD_MAX:entity work.LATCH(arch)
		generic map(W => ABUS)
		port map(reset=>reset, set=> notmode, prevQ=> sram_address, Q=> max_address);

--Todo: buscar como proteger contra desfasaje de coordenadas
--en archivos mal terminados. PODRIA REVISAR ADDRESS%3
COMPARADOR0:process(sram_address, max_address)
	begin
	address_overflow<='1';
	if unsigned(sram_address) < unsigned(max_address) then
		address_overflow<='0';
	end if;
end process;

reset_address<= reset OR (address_overflow AND mode );

MUX0:process( mem_read_add_trig, mem_load, mode)	
	begin
	if mode='1' then
		enable_address_counter<=mem_read_add_trig;
	else
		enable_address_counter<=mem_load;
	end if;
end process;

MUX1:process( mem_load, mem_read, mode)
	begin
	if mode='1' then
		mem<=mem_read;
	else
		mem<=mem_load;
	end if;
end process;


---SIMULATION BEGIN
clk<=not clk after 10 ns;
tx_start<=(done_delayed OR tx_start_bis) AND NOT mode;
tx_start_bis<='0' , '1' after 20 ns, '0' after 40 ns;
reset<='0', '1' after 10 ns, '0' after 20 ns;
rx<=tx;

test_sequence:process
	variable ch : character:='A';
begin
	while not (endfile(datos)) loop
	wait until clk='1' and clk'event ;
		if tx_done_tick='1' then
			READ(datos, ch);
			tx_din<=std_logic_vector(to_unsigned(character'pos(ch),8));
		end if;
	end loop;
       	
	assert false report
                "Fin de Archivo" severity warning;

	wait until clk='1' and clk'event and tx_done_tick='1';
			ch:=character'val(27); -- <ESC>
--			ch:='A';
			tx_din<=std_logic_vector(to_unsigned(character'pos(ch),8));
	wait for 500 us;
	file_close(datos);
	assert false report
		"Bajando Memoria" severity warning;

	dump<=TRUE;
	wait for 20 ns;

	assert false report
		"Termine" severity failure;
	end process;

delayed: process(clk, reset)
		begin
		if reset = '1' then
		done_delayed<='0';
		elsif clk='1' and clk'event then
		done_delayed<=tx_done_tick;
		end if;
	end process;
end arch;
